package com.digital.herbarium.service;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import com.digital.herbarium.Entity.BaseLibrary;
import com.digital.herbarium.Exception.CustomException;
import com.digital.herbarium.Mapper.BaseLibraryMapper;
import com.digital.herbarium.Util.BaseLibraryUtil;
import com.digital.herbarium.Util.ExcelUtilHandler;
import com.digital.herbarium.Util.GetFieldValueUtil;
import com.digital.herbarium.Util.TimeUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class
BaseLibraryService {

    @Autowired
    BaseLibraryMapper baseLibraryMapper;

    public PageInfo<BaseLibrary> getBaseLibraryInfo(BaseLibrary baseLibrary, int pageSize, int  pageNum){
        //return  baseLibraryMapper.getBaseLibraryInfo(baseLibrary);
        PageHelper.startPage(pageNum, pageSize);
        List<BaseLibrary> lists = baseLibraryMapper.getBaseLibraryInfo(baseLibrary);
        PageInfo<BaseLibrary> pageInfo = new PageInfo<BaseLibrary>(lists);
        return pageInfo;
    }


    public List<Map<String,Object>> getBaseLibraryTree(BaseLibrary baseLibrary){
        List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
        List<BaseLibrary> baseLibraryInfo = baseLibraryMapper.getBaseLibraryInfo(baseLibrary);
        int len = baseLibraryInfo.size();
        for (int i = 0; i < len; i++) {
            BaseLibrary bb = baseLibraryInfo.get(i);
            Map<String,Object> map = new HashMap<>();
            boolean ife = checkIfExist(list,"species_family",bb.getSpeciesFamily());
            if(ife){
                continue;
            }
            map.put("species_family",bb.getSpeciesFamily());
            map.put("species_family_name",bb.getSpeciesFamilyName());
            map.put("genus",getChildByKey(baseLibraryInfo,"SpeciesFamily",bb.getSpeciesFamily(),"genus","genus_name","species","genus","Genus","GenusName"));
//            map.put("genus",bb.getGenus());
//            map.put("genus_name",bb.getGenusName());
//            map.put("species",bb.getSpecies());
//            map.put("species_zh_name",bb.getSpeciesZhName());
            list.add(map);
        }
        System.out.println(list.size());
        return list;
    }

    public List<Map<String,Object>> getChildByKey(List<BaseLibrary> blist,String key,String value,String field1,String field2,String children,String check,String key1,String key2){
        List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
        for (int i = 0; i < blist.size(); i++) {
            BaseLibrary bb = blist.get(i);
            String v = GetFieldValueUtil.getValue(bb,key);
            if (v.equals(value)){
                Map<String,Object> map = new HashMap<>();

                boolean ife = checkIfExist(list,check,GetFieldValueUtil.getValue(bb,key1));
                if(ife){
                    continue;
                }
                map.put(field1,GetFieldValueUtil.getValue(bb,key1));
                map.put(field2,GetFieldValueUtil.getValue(bb,key2));
                if(children == null){
                    map.put("children",null);
                }else{
                    map.put(children,getChildByKey(blist,"Genus",bb.getGenus(),"species","species_zh_name",null,"species","Species","SpeciesZhName"));
                }

                list.add(map);
            }

        }
        return list;
    }

    public List<Map<String,Object>> getBaseLibraryTree1(){
        List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
        List<BaseLibrary> baseLibraryInfo = baseLibraryMapper.getBaseLibraryTree();
        List<BaseLibrary> all = baseLibraryMapper.getBaseLibraryInfo(new BaseLibrary());
        int len = baseLibraryInfo.size();
        for (int i = 0; i < len; i++) {
            BaseLibrary bb = baseLibraryInfo.get(i);
            Map<String,Object> map = new HashMap<>();

            map.put("species_family",bb.getSpeciesFamily());
            map.put("species_family_name",bb.getSpeciesFamilyName());
            map.put("genus",getGenusByFamily(all,bb.getSpeciesFamily()));
//            map.put("genus",bb.getGenus());
//            map.put("genus_name",bb.getGenusName());
//            map.put("species",bb.getSpecies());
//            map.put("species_zh_name",bb.getSpeciesZhName());
            list.add(map);
        }
        //System.out.println(list.size());
        return list;
    }

    public List<Map<String,Object>> getGenusByFamily( List<BaseLibrary> blist,String value){
        List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
        for (int i = 0; i < blist.size(); i++) {
            BaseLibrary bl = blist.get(i);
            if(bl.getSpeciesFamily().equals(value)){
                boolean ife = checkIfExist(list,"genus",bl.getGenus());
                if(ife){
                    continue;
                }
                Map<String,Object> map = new HashMap<>();
                map.put("genus",bl.getGenus());
                map.put("genus_name",bl.getGenusName());
                map.put("species",getSpeciesByGenus(blist,bl.getGenus()));
                list.add(map);
            }
        }
        return list;
    }

    public List<Map<String,Object>> getSpeciesByGenus( List<BaseLibrary> blist,String value){
        List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
        for (int i = 0; i < blist.size(); i++) {
            BaseLibrary bl = blist.get(i);
            if(bl.getGenus().equals(value)){
                boolean ife = checkIfExist(list,"species",bl.getSpecies());
                if(ife){
                    continue;
                }
                Map<String,Object> map = new HashMap<>();
                map.put("species",bl.getSpecies());
                map.put("species_zh_name",bl.getSpeciesZhName());
                map.put("canonical_name",bl.getCanonicalName());
                list.add(map);
            }
        }
        return list;
    }



    public boolean checkIfExist(List<Map<String,Object>> list,String key,String value){
        for (int i = 0; i < list.size(); i++) {
            Map<String,Object> map = list.get(i);
            if(map.containsKey(key) && map.get(key).equals(value)){
                return  true;
            }
        }
        return false;
    }



    public void  addBaseLibrary(BaseLibrary baseLibrary){
        BaseLibraryUtil.checkBaseLibraryInfo(baseLibrary);
        //验证物种名字是否已存在
        BaseLibrary b1 = new BaseLibrary();
        b1.setSpeciesZhName(baseLibrary.getSpeciesZhName());
        List<BaseLibrary> bl1 = baseLibraryMapper.getBaseLibraryInfo(b1);
        if(bl1.size() > 0){
            throw  new CustomException(400,"该物种中文名已存在");
        }
        //验证该物种拉丁名是否已存在
        BaseLibrary b2 = new BaseLibrary();
        b2.setCanonicalName(baseLibrary.getCanonicalName());
        List<BaseLibrary> bl2= baseLibraryMapper.getBaseLibraryInfo(b2);
        if(bl2.size() > 0){
            throw  new CustomException(400,"该物种中文名已存在");
        }
        baseLibrary.setState(1);
        baseLibrary.setCreatetime(TimeUtil.getNow());
        baseLibraryMapper.addBaseLibrary(baseLibrary);
    }

    public  void editBaseLibrary(BaseLibrary baseLibrary){
        if(baseLibrary.getId() == null || baseLibrary.getId() == 0){
            throw  new CustomException(400,"缺少信息id");
        }
        BaseLibraryUtil.checkBaseLibraryInfo(baseLibrary);
        //验证物种名字是否已存在
        BaseLibrary b1 = new BaseLibrary();
        b1.setSpeciesZhName(baseLibrary.getSpeciesZhName());
        b1.setId(baseLibrary.getId());
        Integer bl1 = baseLibraryMapper.checkExist(b1);
        if(bl1 > 0){
            throw  new CustomException(400,"该物种中文名已存在");
        }
        //验证该物种拉丁名是否已存在
        BaseLibrary b2 = new BaseLibrary();
        b2.setCanonicalName(baseLibrary.getCanonicalName());
        b2.setId(baseLibrary.getId());
        Integer bl2= baseLibraryMapper.checkExist(b2);
        if(bl2 > 0){
            throw  new CustomException(400,"该物种中文名已存在");
        }
        baseLibraryMapper.editBaseLibrary(baseLibrary);
    }

    public void delBaseLibrary(String id){
        if(StrUtil.hasEmpty(id) || StrUtil.hasBlank(id)){
            throw  new CustomException(400,"缺少信息id");
        }
        String[] strArr = id.split(",");
        Long[] ids = Convert.toLongArray(strArr);
        baseLibraryMapper.delBaseLibrary(ids);
    }


    //解析excel
    public void  addExcel(MultipartFile file, HttpServletRequest request,String uploadPath){
        ExcelReader reader = ExcelUtilHandler.getExcelReader(file, request, uploadPath);
        reader.addHeaderAlias("物种中文名","speciesZhName");
        reader.addHeaderAlias("canonical_name（物种拉丁名）","canonicalName");
        reader.addHeaderAlias("species author","speciesAuthor");
        reader.addHeaderAlias("genus（属）","genus");
        reader.addHeaderAlias("Class（纲）","speciesClass");
        reader.addHeaderAlias("Order（目）","speciesOrder");
        reader.addHeaderAlias("Family（科）","speciesFamily");
        reader.addHeaderAlias("科中文名","speciesFamilyName");
        reader.addHeaderAlias("属中文名","genusName");
        reader.addHeaderAlias("species(种加词)","species");
        reader.addHeaderAlias("infraspecies","infraspecies");
        reader.addHeaderAlias("infraspecies2","infraspecies2");
        reader.addHeaderAlias("infraspecies_c","infraspeciesC");
        reader.addHeaderAlias("infraspecies_c2","infraspeciesC2");
        reader.addHeaderAlias("infraspecies_marker","infraspeciesMarker");
        reader.addHeaderAlias("infraspecies_marker2","infraspeciesMarker2");
        reader.addHeaderAlias("author2","author2");
        reader.addHeaderAlias("comment","comment");
        reader.addHeaderAlias("scrutiny_date","scrutinyDate");
        reader.addHeaderAlias("sp2000_status_id","sp2000StatusId");
        reader.addHeaderAlias("database_id","databaseId");
        reader.addHeaderAlias("specialist_id","specialistId");
        reader.addHeaderAlias("family_id","familyId");
        reader.addHeaderAlias("is_accepted_name","isAcceptedName");
        reader.addHeaderAlias("genus_c_py","genusCPy");
        reader.addHeaderAlias("species_c_py","speciesCPy");
        reader.addHeaderAlias("infraspecies_c_py","infraspeciesCPy");
        reader.addHeaderAlias("infraspecies_c_py2","infraspeciesCPy2");
        reader.addHeaderAlias("genuswithsubgenus","genuswithsubgenus");
        reader.addHeaderAlias("specialist_code","specialistCode");
        reader.addHeaderAlias("family_code","familyCode");
        reader.addHeaderAlias("comments","comments");
        List<BaseLibrary> baseLibrary = reader.readAll( BaseLibrary.class);
        //添加
        baseLibrary.forEach(bl -> {
            bl.setCreatetime(TimeUtil.getNow());
        });
        batchInsert(baseLibrary);

    }


    public void batchInsert( List<BaseLibrary> list )
    {
        int	len	= list.size();
        int	mod	= 1000;
        int	n	= len % mod == 0 ? len / mod : len / mod + 1;
        int	start	= 0;
        int	pos	= 0;
        int	k	= mod;
        List	subList = null;
        for ( int i = 0; i < n; i++ )
        {
            if ( len / (i + 1) < mod )
            {
                k = len % mod;
            }
            pos	+= k;
            subList = list.subList( start, pos );
            baseLibraryMapper.bachAdd( subList );
            start += mod;
        }
    }

}
